home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * (a) (C) 1990 by Adobe Systems Incorporated. All rights reserved.
- *
- * (b) If this Sample Code is distributed as part of the Display PostScript
- * System Software Development Kit from Adobe Systems Incorporated,
- * then this copy is designated as Development Software and its use is
- * subject to the terms of the License Agreement attached to such Kit.
- *
- * (c) If this Sample Code is distributed independently, then the following
- * terms apply:
- *
- * (d) This file may be freely copied and redistributed as long as:
- * 1) Parts (a), (d), (e) and (f) continue to be included in the file,
- * 2) If the file has been modified in any way, a notice of such
- * modification is conspicuously indicated.
- *
- * (e) PostScript, Display PostScript, and Adobe are registered trademarks of
- * Adobe Systems Incorporated.
- *
- * (f) THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO
- * CHANGE WITHOUT NOTICE, AND SHOULD NOT BE CONSTRUED
- * AS A COMMITMENT BY ADOBE SYSTEMS INCORPORATED.
- * ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY
- * OR LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO
- * WARRANTY OF ANY KIND (EXPRESS, IMPLIED OR STATUTORY)
- * WITH RESPECT TO THIS INFORMATION, AND EXPRESSLY
- * DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT
- * OF THIRD PARTY RIGHTS.
- */
-
- /*
- * epsfparser.m
- *
- * ReadEpsf() is the procedure to invoke for parsing. It takes a pointer
- * to a structure as an argument. This structure contains the pointer to
- * the data as well as the locations to place the results of the parsing.
- * This parser grabs the bounding box and the fonts. Other parsers
- * can add to this general structure to do more sophisticated parsing
- * such as page breakout and such.
- *
- * Version: 2.0
- * Author: Ken Fromm
- * History:
- * 03-19-91 Added this comment.
- */
-
- #import "epsfstruct.h"
-
- #import <appkit/nextstd.h>
- #import <objc/hashtable.h>
- #import <objc/List.h>
- #import <objc/Storage.h>
- #import <strings.h>
-
- static int processToField(EpsfStruct *epsf);
- static int processToLineEnd(EpsfStruct *epsf);
-
- static int processBBox(EpsfStruct *epsf);
- static int processIncludeFile(EpsfStruct *epsf);
- static int processToEndDocument(EpsfStruct *epsf);
- static int processDocumentResource(EpsfStruct *epsf);
- static int processPageCount(EpsfStruct *epsf);
-
- /*
- * These static CommentHandle arrays are organized
- * into different groups according to the level of the
- * parsing. The general comments handle the top most
- * level of parsing. The document comments handle
- * the parsing of an included document.
- *
- * This setup allows the same general flow to handle the
- * parsing of each group. When a comment is reached
- * that indicates another level of parsing should be
- * performed, the tables for that level is passed to the
- * processToComment procedure.
- *
- * Others group could be added (not necessarily for
- * Epsf inclusion but for print management parsing). One
- * example is a page comment group. This group would
- * parse the page comments breaking out the location
- * of the individual pages as well as fonts, colors, paper
- * sizes, etc.
- *
- */
-
- typedef struct {
- char *comment; int (*proc) (EpsfStruct *epsf);
- } CommentHandle;
-
- /***** General comments *****/
- static CommentHandle generalComments [ ] =
- {
- {"%%BoundingBox:", processBBox},
- {"%%BeginDocument", processToEndDocument},
- {"%%Document", processDocumentResource},
- {"%%Pages:", processPageCount}
- };
-
- /***** Document comments *****/
- static CommentHandle documentIncludeComments [ ] =
- {
- {"%%BeginDocument", processToEndDocument},
- {"%%IncludeFile", processIncludeFile}
- };
-
- /***** Document comments *****/
- static CommentHandle documentEndComments [ ] =
- {
- {"%%EndDocument", processToLineEnd}
- };
-
-
- /*
- * These static arrays are used to recognize the types of resources.
- * For starters there are at present 5 types of resources - fonts, files,
- * procsets, patterns and forms. Within each type, there are 3 states -
- * present, needed and supplied. The present state is the union of the
- * needed and supplied. The needed means the resource is not included
- * with the document. The supplied means the resource is included with
- * the document.
- */
-
- typedef struct {
- char *comment; int key;
- } ResourceHandle;
-
- /***** Resource comments *****/
- static ResourceHandle resourceStates [ ] =
- {
- {"Needed", RES_NEEDED},
- {"Supplied", RES_SUPPLIED}
- };
-
- static ResourceHandle resourceTypeMain [ ] =
- {
- {"Fonts", RES_FONTS},
- {"Files", RES_FILES},
- {"ProcSets", RES_PROCSETS},
- {"Patterns", RES_PATTERNS},
- {"Forms", RES_FORMS},
- {"Resources", RES_RESOURCES},
- };
-
- static ResourceHandle resourceTypeSub [ ] =
- {
- {"fonts", RES_FONTS},
- {"files", RES_FILES},
- {"procsets", RES_PROCSETS},
- {"patterns", RES_PATTERNS},
- {"forms", RES_FORMS}
- };
-
- /*
- * This is the workhorse of the parser. It takes a general structure
- * and some pointers to CommentHandle arrays and processes
- * the data until the one of the comments in the endTable has
- * been reached or the data runs out. Any matches to the
- * processTable comments processes the comment without
- * returning. (Any match to the endTable returns after processing.)
- *
- * If endLength is 0 then we will only process until the next line that
- * is not a comment.
- */
- static int processToComment(EpsfStruct *epsf, CommentHandle endTable[ ], int endLength,
- CommentHandle processTable[ ], int processLength)
- {
- int i, j;
-
- while (epsf->data < epsf->enddata)
- {
- if (strncmp(epsf->data, "%", 1) == 0)
- {
- for (j = 0; j < endLength; j++)
- {
- if (strncmp(epsf->data, endTable[j].comment,
- strlen(endTable[j].comment)) == 0)
- {
- return endTable[j].proc(epsf);
- }
- }
-
- for (i = 0; i < processLength; i++)
- {
- if (strncmp(epsf->data, processTable[i].comment,
- strlen(processTable[i].comment)) == 0)
- {
- processTable[i].proc(epsf);
- break;
- }
- }
-
- if (i == processLength)
- processToLineEnd(epsf);
- }
- else
- {
- /* If endLength == 0 then process until the next non-comment. */
- if (endLength == 0)
- return EPSF_OK;
- else
- processToLineEnd(epsf);
- }
- }
-
- return EPSF_OK;
- }
-
- static int CheckEpsf(EpsfStruct *epsf)
- {
- int rc = EPSF_INVALIDPS;
-
- if (strncmp(epsf->data, "%!PS-Adobe-", 11) == 0)
- {
- processToField(epsf);
- if (strncmp(epsf->data, "EPSF-", 5) == 0)
- {
- processToLineEnd(epsf);
- rc = EPSF_OK;
- }
- }
-
- return rc;
- }
-
- void CheckEpsfBinaryHeader(char **data, int *len)
- {
- EpsfBinaryHeader *header;
-
- char *newdata;
-
- int newlen;
-
- /*
- * If a binary header file is encountered then just skip
- * to the PostScript section of the file. Update the
- * data and len arguments to reflect this change.
- */
- header = (EpsfBinaryHeader *) *data;
- if (header->idbytes == EPSF_BINARYID)
- {
- newdata = *data + header->ps_start;
- newlen = header->ps_length;
-
- if (newdata >= *data && newdata + newlen <= *data + *len)
- {
- *data = newdata;
- *len = newlen;
- }
- }
- }
-
- /*
- * This is the routine invoked for parsing. It validates the file
- * as a proper EPSF file (by checking for the %!PS-Adobe or
- * for the binary header id) and then parses the file.
- */
- int ReadEpsf(EpsfStruct *epsf)
- {
- int rc = EPSF_OK;
-
- if (epsf && epsf->filedata && *epsf->filedata)
- {
- CheckEpsfBinaryHeader(&epsf->filedata, &epsf->filelen);
- epsf->data = epsf->filedata;
- epsf->enddata = epsf->filedata + epsf->filelen;
-
- if (epsf->data < epsf->enddata && !CheckEpsf(epsf))
- {
- bzero(epsf->bbox, sizeof(epsf->bbox));
- bzero(&epsf->resources, sizeof(epsf->resources));
- bzero(&epsf->inclusions, sizeof(epsf->inclusions));
-
- while (epsf->data < epsf->enddata && !rc)
- {
- rc = processToComment(epsf,
- generalComments, sizeof(generalComments)/sizeof(CommentHandle),
- NULL, 0);
- }
-
- /* Check for a valid bounding box. */
- if (!rc && epsf->bbox[0] == 0 && epsf->bbox[1] == 0 &&
- epsf->bbox[2] == 0 && epsf->bbox[3] == 0)
- rc = EPSF_INVALIDBBOX;
- }
- else
- rc = EPSF_INVALIDPS;
- }
- else
- rc = EPSF_INVALIDPS;
-
- return rc;
- }
-
- static int processToNonSpace(EpsfStruct *epsf)
- {
- while (epsf->data < epsf->enddata && *epsf->data == ' ')
- epsf->data++;
-
- return EPSF_OK;
- }
-
- static int processToField(EpsfStruct *epsf)
- {
-
- while (epsf->data < epsf->enddata && *epsf->data != ':' && *epsf->data != ' ')
- epsf->data++;
- if (epsf->data < epsf->enddata && *epsf->data == ':')
- epsf->data++;
- processToNonSpace(epsf);
-
- return EPSF_OK;
- }
-
- static int processToLineEnd(EpsfStruct *epsf)
- {
- while (epsf->data < epsf->enddata && *epsf->data != '\n')
- epsf->data++;
- if (epsf->data < epsf->enddata)
- epsf->data++;
-
- return EPSF_OK;
- }
-
- static int processBBox(EpsfStruct *epsf)
- {
-
- int rc = EPSF_OK;
-
- processToField(epsf);
- if (epsf->data < epsf->enddata && strncmp(epsf->data, "(atend)", 7) != 0)
- if ((sscanf(epsf->data, "%f %f %f %f", &epsf->bbox[0], &epsf->bbox[1],
- &epsf->bbox[2], &epsf->bbox[3]) != 4) ||
- epsf->bbox[2] <= epsf->bbox[0] || epsf->bbox[3] <= epsf->bbox[1])
- rc = EPSF_INVALIDBBOX;
-
- processToLineEnd(epsf);
-
- return rc;
- }
-
- static int processIncludeFile(EpsfStruct *epsf)
- {
- int rc = EPSF_OK;
-
- char name[EPSF_MAXLINE];
-
- Inclusion inclusion;
-
- bzero(&inclusion, sizeof(inclusion));
-
- inclusion.offset = epsf->data - epsf->filedata;
- processToField(epsf);
- if (epsf->data < epsf->enddata)
- {
- if (sscanf(epsf->data, "%s", name))
- inclusion.filename = NXUniqueString(name);
-
- processToLineEnd(epsf);
- inclusion.len = (epsf->data - epsf->filedata) - inclusion.offset;
-
- if (inclusion.filename)
- {
- if (!epsf->inclusions)
- epsf->inclusions= [Storage newCount:0 elementSize:sizeof(Inclusion) description:InclusionDescription];
-
- [epsf->inclusions addElement:&inclusion];
- }
- }
- else
- rc = EPSF_INVALIDDOCUMENT;
-
- return rc;
- }
-
- static int processToEndDocument(EpsfStruct *epsf)
- {
- processToLineEnd(epsf);
- processToComment(epsf,
- documentEndComments,
- sizeof(documentEndComments)/sizeof(CommentHandle),
- documentIncludeComments,
- sizeof(documentIncludeComments)/sizeof(CommentHandle));
-
- if (epsf->data >= epsf->enddata)
- return EPSF_INVALIDDOCUMENT;
- else
- return EPSF_OK;
- }
-
- /* Checks the page count. If greater than 1, an error is returned. */
- /* Eps files should be single page documents only. */
- static int processPageCount(EpsfStruct *epsf)
- {
- int rc = EPSF_OK;
-
- int pagetotal = 0;
-
- processToField(epsf);
- if (epsf->data < epsf->enddata && strncmp(epsf->data, "(atend)", 7) != 0)
- if (sscanf(epsf->data, "%d", &pagetotal))
- if (pagetotal > 1)
- rc = EPSF_INVALIDPAGECOUNT;
-
- processToLineEnd(epsf);
-
- return rc;
- }
-
- static int checkResource(EpsfStruct *epsf, ResourceHandle table[ ], int length)
- {
- int i;
-
- for (i = 0; i < length; i++)
- {
- if (epsf->data < epsf->enddata &&
- strncmp(epsf->data, table[i].comment, strlen(table[i].comment)) == 0)
- {
- epsf->data += strlen(table[i].comment);
- return table[i].key;
- }
- }
-
- return -1;
- }
-
- static int processResourceLine(EpsfStruct *epsf, int type, int state)
- {
- int i;
-
- char name[EPSF_MAXLINE], temp[40];
-
- if (!epsf->resources[type].states[state])
- epsf->resources[type].states[state] = [List new];
-
- processToNonSpace(epsf);
- while (epsf->data < epsf->enddata && *epsf->data != '\n')
- {
- sscanf(epsf->data, "%s", name);
- epsf->data += strlen(name);
- processToNonSpace(epsf);
- if (type == RES_PROCSETS)
- {
- for (i = 0; i < 2 && epsf->data < epsf->enddata && *epsf->data != '\n'; i++)
- {
- if (sscanf(epsf->data, "%s", temp))
- {
- strcat(name, " ");
- strcat(name, temp);
- epsf->data += strlen(temp);
- processToNonSpace(epsf);
- }
- }
- }
- [epsf->resources[type].states[state]
- addObjectIfAbsent:(id) NXUniqueString(name)];
- }
-
- return EPSF_OK;
- }
-
- static int processResources(EpsfStruct *epsf, int xtype, int state)
- {
- int done = FALSE, type;
-
- type = xtype;
- processToField(epsf);
- if (epsf->data < epsf->enddata && strncmp(epsf->data, "(atend)", 7) != 0)
- {
- while (epsf->data < epsf->enddata && !done )
- {
- processToNonSpace(epsf);
- if (*epsf->data == '\n')
- {
- epsf->data++;
- if (epsf->data < epsf->enddata && strncmp(epsf->data, "%%+", 3) == 0)
- epsf->data += 3;
- else
- done = TRUE;
- }
- else
- {
- if (xtype == RES_RESOURCES)
- type = checkResource(epsf, resourceTypeSub,
- sizeof(resourceTypeSub)/sizeof(ResourceHandle));
-
- if (type >= RES_FONTS && type <= RES_FORMS)
- processResourceLine(epsf, type, state);
- else
- while (epsf->data < epsf->enddata && *epsf->data != '\n')
- epsf->data++;
- }
- }
- }
- else
- processToLineEnd(epsf);
-
- return EPSF_OK;
- }
-
- static int processDocumentResource(EpsfStruct *epsf)
- {
- int state, type;
-
- epsf->data += 10;
- if (epsf->data < epsf->enddata)
- {
- state = checkResource(epsf, resourceStates,
- sizeof(resourceStates)/sizeof(ResourceHandle));
- state = MAX(RES_PRESENT, state);
- type = checkResource(epsf, resourceTypeMain,
- sizeof(resourceTypeMain)/sizeof(ResourceHandle));
- if (type >= 0)
- processResources(epsf, type, state);
- }
-
- return EPSF_OK;
- }
-
- static char *getResource(int key, ResourceHandle table[ ], int length)
- {
- int i;
-
- for (i = 0; i < length; i++)
- if (table[i].key == key)
- return table[i].comment;
-
- return NULL;
- }
-
- void GetDocumentComment(char *comment, int type, int state)
- {
- char *subOne, *subTwo;
-
- strcpy(comment, "%%%%Document");
- subOne = getResource(state, resourceStates,
- sizeof(resourceStates)/sizeof(ResourceHandle));
- if (subOne)
- strcat(comment, subOne);
- subTwo = getResource(type, resourceTypeMain,
- sizeof(resourceTypeMain)/sizeof(ResourceHandle));
- if (subTwo)
- strcat(comment, subTwo);
- strcat(comment, ": ");
- }
-
- const char *GetTypeComment(int type)
- {
- return getResource(type, resourceTypeMain,
- sizeof(resourceTypeMain)/sizeof(ResourceHandle));
- }
-
-
-